home *** CD-ROM | disk | FTP | other *** search
/ Software Vault: The Diamond Collection / The Diamond Collection (Software Vault)(Digital Impact).ISO / cdr44 / frasrc19.zip / MISCOVL.C < prev    next >
C/C++ Source or Header  |  1995-03-04  |  64KB  |  2,037 lines

  1. /*
  2.     Overlayed odds and ends that don't fit anywhere else.
  3. */
  4.  
  5. #include <stdlib.h>
  6. #include <stdio.h>
  7. #include <string.h>
  8. #include <ctype.h>
  9. #ifndef XFRACT
  10. #include <malloc.h>
  11. #include <process.h>
  12. #include <dos.h>
  13. #include <stdarg.h>
  14. #include <io.h>
  15. #else
  16. #include <varargs.h>
  17. #endif
  18. #include "fractint.h"
  19. #include "fractype.h"
  20. #include "helpdefs.h"
  21. #include "prototyp.h"
  22.  
  23. /* routines in this module    */
  24.  
  25. static void write_batch_parms(char *colorinf,int maxcolor);
  26.  
  27. #ifndef XFRACT
  28. static void put_parm(char *parm,...);
  29. #else
  30. static void put_parm();
  31. #endif
  32.  
  33. static void put_parm_line(void);
  34. static int getprec(double,double,double);
  35. extern int getprecbf(int);
  36. static void put_float(int,double,int);
  37. static void put_bf(int slash,bf_t r, int prec);
  38. static void put_filename(char *keyword,char *fname);
  39. static int check_modekey(int curkey,int choice);
  40. static int entcompare(VOIDCONSTPTR p1,VOIDCONSTPTR p2);
  41. static void update_fractint_cfg(void);
  42.  
  43. /* fullscreen_choice options */
  44. #define CHOICERETURNKEY 1
  45. #define CHOICEMENU    2
  46. #define CHOICEHELP    4
  47.  
  48. char s_yes[]      = "yes";
  49. char s_no[]       = "no";
  50. char s_seqs[]     = " %s=%s";
  51. char s_seqd[]     = " %s=%d";
  52. char s_seqdd[]    = " %s=%d/%d";
  53. char s_seqddd[]   = " %s=%d/%d/%d";
  54. char s_seqdddd[]  = " %s=%d/%d/%d/%d";
  55. char s_x[]        = "x";
  56. char s_y[]        = "y";
  57. char s_z[]        = "z";
  58.  
  59. /* JIIM */
  60.  
  61. FILE *parmfile;
  62.  
  63. #define PAR_KEY(x)  ( x < 10 ? '0' + x : 'a' - 10 + x)
  64.  
  65. #ifdef C6
  66. #pragma optimize("e",off)  /* MSC 6.00A messes up next rtn with "e" on */
  67. #endif
  68.  
  69. #define LOADBATCHPROMPTS(X)     {\
  70.    static FCODE tmp[] = { X };\
  71.    far_strcpy(ptr,tmp);\
  72.    choices[promptnum]= ptr;\
  73.    ptr += sizeof(tmp);\
  74.    }
  75.  
  76.  
  77. void make_batch_file()
  78. {
  79. #define MAXPROMPTS 18
  80.    static char far hdg[]={"Save Current Parameters"};
  81.    /** added for pieces feature **/
  82.    double pdelx;
  83.    double pdely;
  84.    double pdelx2;
  85.    double pdely2;
  86.    unsigned int j, pxdots, pydots, xm, ym;
  87.    double pxxmin, pyymax;
  88.    char vidmde[4];
  89.    int promptnum;
  90.    int piecespromts;
  91.    int have3rd;
  92.    /****/
  93.  
  94.    int i;
  95.    char far *inpcommandfile, far *inpcommandname;
  96.    char far *inpcomment1, far *inpcomment2, far *inpcomment3, far *inpcomment4;
  97.    struct fullscreenvalues paramvalues[18];
  98.    char far * choices[MAXPROMPTS];
  99.    char far *ptr;
  100.    int gotinfile;
  101.    char outname[81], buf[256], buf2[128];
  102.    FILE *infile;
  103.    FILE *fpbat = NULL;
  104.    char colorspec[14];
  105.    int maxcolor;
  106.    int maxcolorindex;
  107.    char *sptr, *sptr2;
  108.    int oldhelpmode;
  109.  
  110.    /* put comment storage in extraseg */
  111.    inpcommandfile = MK_FP(extraseg,0);
  112.    inpcommandname = inpcommandfile+80;
  113.    inpcomment1    = inpcommandname+(ITEMNAMELEN + 1);
  114.    inpcomment2    = inpcomment1 + 57;
  115.    inpcomment3    = inpcomment2 + 57;
  116.    inpcomment4    = inpcomment3 + 57;
  117.    
  118.    /* steal existing array for "choices" */
  119.    ptr = (char far *)(inpcomment4 + 57);
  120.    stackscreen();
  121.    oldhelpmode = helpmode;
  122.    helpmode = HELPPARMFILE;
  123.  
  124.    strcpy(colorspec, "n");
  125.    maxcolor = colors;
  126.    if (gotrealdac && !reallyega)
  127.    {
  128.       --maxcolor;
  129. /*    if (maxit < maxcolor)  remove 2 lines */
  130. /*       maxcolor = maxit;   so that whole palette is always saved */
  131.       if (inside > 0 && inside > maxcolor)
  132.          maxcolor = inside;
  133.       if (outside > 0 && outside > maxcolor)
  134.          maxcolor = outside;
  135.       if (distest < 0 && 0 - distest > maxcolor)
  136.          maxcolor = 0 - distest;
  137.       if (decomp[0] > maxcolor)
  138.          maxcolor = decomp[0] - 1;
  139.       if (potflag && potparam[0] >= maxcolor)
  140.          maxcolor = (int)potparam[0];
  141.       if (++maxcolor > 256)
  142.          maxcolor = 256;
  143.       if (colorstate == 0)
  144.       {                         /* default colors */
  145.          if (mapdacbox)
  146.          {
  147.             colorspec[0] = '@';
  148.             sptr = MAP_name;
  149.          }
  150.       }
  151.       else
  152.       if (colorstate == 2)
  153.       {                         /* colors match colorfile */
  154.          colorspec[0] = '@';
  155.          sptr = colorfile;
  156.       }
  157.       else                      /* colors match no .map that we know of */
  158.          colorspec[0] = 'y';
  159.       if (colorspec[0] == '@')
  160.       {
  161.          if ((sptr2 = strrchr(sptr, SLASHC)) != NULL)
  162.             sptr = sptr2 + 1;
  163.          if ((sptr2 = strrchr(sptr, ':')) != NULL)
  164.             sptr = sptr2 + 1;
  165.          strncpy(&colorspec[1], sptr, 12);
  166.          colorspec[13] = 0;
  167.       }
  168.    }
  169.    far_strcpy(inpcommandfile, CommandFile);
  170.    far_strcpy(inpcommandname, CommandName);
  171.    far_strcpy(inpcomment1, CommandComment1);
  172.    far_strcpy(inpcomment2, CommandComment2);
  173.    far_strcpy(inpcomment3, CommandComment3);
  174.    far_strcpy(inpcomment4, CommandComment4);
  175.    if (CommandName[0] == 0)
  176.       far_strcpy(inpcommandname, "test");
  177.       /* TW added these  - and Bert moved them */
  178.       pxdots = xdots;
  179.       pydots = ydots;
  180.       vidmode_keyname(videoentry.keynum, vidmde);
  181.  
  182.       xm = ym = 1;
  183.  
  184.    for(;;)
  185.    {
  186. prompt_user:
  187.       promptnum = 0;
  188.       LOADBATCHPROMPTS("Parameter file");
  189.       paramvalues[promptnum].type = 0x100 + 56;
  190.       paramvalues[promptnum++].uval.sbuf = inpcommandfile;
  191.       LOADBATCHPROMPTS("Name");
  192.       paramvalues[promptnum].type = 0x100 + ITEMNAMELEN;
  193.       paramvalues[promptnum++].uval.sbuf = inpcommandname;
  194.       LOADBATCHPROMPTS("Main comment");
  195.       paramvalues[promptnum].type = 0x100 + 56;
  196.       paramvalues[promptnum++].uval.sbuf = inpcomment1;
  197.       LOADBATCHPROMPTS("Second comment");
  198.       paramvalues[promptnum].type = 0x100 + 56;;
  199.       paramvalues[promptnum++].uval.sbuf = inpcomment2;
  200.       LOADBATCHPROMPTS("Third comment");
  201.       paramvalues[promptnum].type = 0x100 + 56;;
  202.       paramvalues[promptnum++].uval.sbuf = inpcomment3;
  203.       LOADBATCHPROMPTS("Fourth comment");
  204.       paramvalues[promptnum].type = 0x100 + 56;;
  205.       paramvalues[promptnum++].uval.sbuf = inpcomment4;
  206.       if (gotrealdac && !reallyega)
  207.       {
  208.          LOADBATCHPROMPTS("Record colors?");
  209.          paramvalues[promptnum].type = 0x100 + 13;
  210.          paramvalues[promptnum++].uval.sbuf = colorspec;
  211.          LOADBATCHPROMPTS("    (no | yes for full info | @filename to point to a map file)");
  212.          paramvalues[promptnum++].type = '*';
  213.          LOADBATCHPROMPTS("# of colors");
  214.          maxcolorindex = promptnum;
  215.          paramvalues[promptnum].type = 'i';
  216.          paramvalues[promptnum++].uval.ival = maxcolor;
  217.          LOADBATCHPROMPTS("    (if recording full color info)");
  218.          paramvalues[promptnum++].type = '*';
  219.       }
  220.       LOADBATCHPROMPTS("");
  221.       paramvalues[promptnum++].type = '*';
  222.       LOADBATCHPROMPTS("    **** The following is for generating images in pieces ****");
  223.       paramvalues[promptnum++].type = '*';
  224.       LOADBATCHPROMPTS("X Multiples");
  225.       piecespromts = promptnum;
  226.       paramvalues[promptnum].type = 'i';
  227.       paramvalues[promptnum++].uval.ival = xm;
  228.       LOADBATCHPROMPTS("Y Multiples");
  229.       paramvalues[promptnum].type = 'i';
  230.       paramvalues[promptnum++].uval.ival = ym;
  231. #ifndef XFRACT
  232.       LOADBATCHPROMPTS("Video mode");
  233.       paramvalues[promptnum].type = 0x100 + 4;
  234.       paramvalues[promptnum++].uval.sbuf = vidmde;
  235. #endif
  236.  
  237.       if (fullscreen_prompt(hdg,promptnum, choices, paramvalues, 0, NULL) < 0)
  238.          break;
  239.  
  240.       far_strcpy(CommandFile, inpcommandfile);
  241.       if (strchr(CommandFile, '.') == NULL)
  242.          strcat(CommandFile, ".par");   /* default extension .par */
  243.       far_strcpy(CommandName, inpcommandname);
  244.       far_strcpy(CommandComment1, inpcomment1);
  245.       far_strcpy(CommandComment2, inpcomment2);
  246.       far_strcpy(CommandComment3, inpcomment3);
  247.       far_strcpy(CommandComment4, inpcomment4);
  248.       if (gotrealdac && !reallyega)
  249.          if (paramvalues[maxcolorindex].uval.ival > 0 &&
  250.              paramvalues[maxcolorindex].uval.ival <= 256)
  251.             maxcolor = paramvalues[maxcolorindex].uval.ival;
  252.  
  253.       promptnum = piecespromts;
  254.       xm = paramvalues[promptnum++].uval.ival;
  255.  
  256.       ym = paramvalues[promptnum++].uval.ival;
  257.  
  258.       /* sanity checks */
  259.       {
  260.       int i;
  261.       long xtotal, ytotal;
  262.  
  263.       /* get resolution from the video name (which must be valid) */
  264. #ifndef XFRACT
  265.       pxdots = pydots = 0;
  266.       if ((i = check_vidmode_keyname(vidmde)) > 0)
  267.           if ((i = check_vidmode_key(0, i)) >= 0) {
  268.               /* get the resolution of this video mode */
  269.               pxdots = videotable[i].xdots;
  270.               pydots = videotable[i].ydots;
  271.               }
  272.       if (pxdots == 0 && (xm > 1 || ym > 1)) {
  273.           /* no corresponding video mode! */
  274.           static FCODE msg[] = {"Invalid video mode entry!"};
  275.           stopmsg(0,msg);
  276.           goto prompt_user;
  277.           }
  278. #endif
  279.  
  280.       /* bounds range on xm, ym */
  281.       if (xm < 1 || xm > 36 || ym < 1 || ym > 36) {
  282.           static FCODE msg[] = {"X and Y components must be 1 to 36"};
  283.           stopmsg(0,msg);
  284.           goto prompt_user;
  285.           }
  286.  
  287.       /* another sanity check: total resolution cannot exceed 65535 */
  288.       xtotal = xm;  ytotal = ym;
  289.       xtotal *= pxdots;  ytotal *= pydots;
  290.       if (xtotal > 65535L || ytotal > 65535L) {
  291.       static FCODE msg[] = {"Total resolution (X or Y) cannot exceed 65535"};
  292.           stopmsg(0,msg);
  293.           goto prompt_user;
  294.           }
  295.       }
  296.  
  297.       strcpy(outname, CommandFile);
  298.       gotinfile = 0;
  299.       if (access(CommandFile, 0) == 0)
  300.       {                         /* file exists */
  301.          gotinfile = 1;
  302.          if (access(CommandFile, 6))
  303.          {
  304.             sprintf(buf, s_cantwrite, CommandFile);
  305.             stopmsg(0, buf);
  306.             continue;
  307.          }
  308.          i = strlen(outname);
  309.          while (--i >= 0 && outname[i] != SLASHC)
  310.             outname[i] = 0;
  311.          strcat(outname, "fractint.tmp");
  312.          infile = fopen(CommandFile, "rt");
  313. #ifndef XFRACT
  314.          setvbuf(infile, tstack, _IOFBF, 4096); /* improves speed */
  315. #endif
  316.       }
  317.       if ((parmfile = fopen(outname, "wt")) == NULL)
  318.       {
  319.          sprintf(buf, s_cantcreate, outname);
  320.          stopmsg(0, buf);
  321.          if (gotinfile)
  322.             fclose(infile);
  323.          continue;
  324.       }
  325.  
  326.       if (gotinfile)
  327.       {
  328.          while (file_gets(buf, 255, infile) >= 0)
  329.          {
  330.             if (strchr(buf, '{')/* entry heading? */
  331.                 && sscanf(buf, " %40[^ \t({]", buf2)
  332.                 && stricmp(buf2, CommandName) == 0)
  333.             {                   /* entry with same name */
  334.                static FCODE s1[] = {"File already has an entry named "};
  335.                static FCODE s2[] = {"\n\
  336. Continue to replace it, Cancel to back out"};
  337.                far_strcpy(buf2,s1);
  338.                far_strcat(buf2,CommandName);
  339.                far_strcat(buf2,s2);
  340.                if (stopmsg(18, buf2) < 0)
  341.                {                /* cancel */
  342.                   fclose(infile);
  343.                   fclose(parmfile);
  344.                   unlink(outname);
  345.                   goto prompt_user;
  346.                }
  347.                while (strchr(buf, '}') == NULL
  348.                       && file_gets(buf, 255, infile) > 0)
  349.                   ; /* skip to end of set */
  350.                break;
  351.             }
  352.             fputs(buf, parmfile);
  353.             fputc('\n', parmfile);
  354.          }
  355.       }
  356. /***** start here*/
  357.       if (xm > 1 || ym > 1)
  358.       {
  359.          if (xxmin != xx3rd || yymin != yy3rd)
  360.             have3rd = 1;
  361.          else
  362.             have3rd = 0;
  363.          if ((fpbat = dir_fopen(workdir,"makemig.bat", "w")) == NULL)
  364.             xm = ym = 0;
  365.          pdelx  = (xxmax - xx3rd) / (xm * pxdots - 1);   /* calculate stepsizes */
  366.          pdely  = (yymax - yy3rd) / (ym * pydots - 1);
  367.          pdelx2 = (xx3rd - xxmin) / (ym * pydots - 1);
  368.          pdely2 = (yy3rd - yymin) / (xm * pxdots - 1);
  369.  
  370.          /* save corners */
  371.          pxxmin = xxmin;
  372.          pyymax = yymax;
  373.       }
  374.       for (i = 0; i < (int)xm; i++)  /* columns */
  375.       for (j = 0; j < (unsigned int)ym; j++)  /* rows    */
  376.       {
  377.          if (xm > 1 || ym > 1)
  378.          {
  379.             int w;
  380.             char c;
  381.             char PCommandName[80];
  382.             w=0;
  383.             while(w < (int)strlen(CommandName))
  384.             {
  385.                c = CommandName[w];
  386.                if(isspace(c) || c == 0)
  387.                   break;
  388.                PCommandName[w] = c;
  389.                w++;
  390.             }
  391.             PCommandName[w] = 0;
  392.             {
  393.                char buf[20];
  394.                sprintf(buf,"_%c%c",PAR_KEY(i),PAR_KEY(j));
  395.                strcat(PCommandName,buf);
  396.             }
  397.             fprintf(parmfile, "%-19s{",PCommandName);
  398.             xxmin = pxxmin + pdelx*(i*pxdots) + pdelx2*(j*pydots);
  399.             xxmax = pxxmin + pdelx*((i+1)*pxdots - 1) + pdelx2*((j+1)*pydots - 1);
  400.             yymin = pyymax - pdely*((j+1)*pydots - 1) - pdely2*((i+1)*pxdots - 1);
  401.             yymax = pyymax - pdely*(j*pydots) - pdely2*(i*pxdots);
  402.             if (have3rd)
  403.             {
  404.                xx3rd = pxxmin + pdelx*(i*pxdots) + pdelx2*((j+1)*pydots - 1);
  405.                yy3rd = pyymax - pdely*((j+1)*pydots - 1) - pdely2*(i*pxdots);
  406.             }
  407.             else
  408.             {
  409.                xx3rd = xxmin;
  410.                yy3rd = yymin;
  411.             }
  412.             fprintf(fpbat,"Fractint batch=yes overwrite=yes @%s/%s\n",CommandFile,PCommandName);
  413.             fprintf(fpbat,"If Errorlevel 2 goto oops\n");
  414.          }
  415.          else
  416.             fprintf(parmfile, "%-19s{", CommandName);
  417.          if (CommandComment1[0])
  418.             fprintf(parmfile, " ; %s", CommandComment1);
  419.          fputc('\n', parmfile);
  420.          {
  421.             char buf[25];
  422.             memset(buf, ' ', 23);
  423.             buf[23] = 0;
  424.             buf[21] = ';';
  425.             if (CommandComment2[0])
  426.                fprintf(parmfile, "%s%s\n", buf, CommandComment2);
  427.             if (CommandComment3[0])
  428.                fprintf(parmfile, "%s%s\n", buf, CommandComment3);
  429.             if (CommandComment4[0])
  430.                fprintf(parmfile, "%s%s\n", buf, CommandComment4);
  431.          }
  432.          write_batch_parms(colorspec, maxcolor);   /* write the parameters */
  433.          if(xm > 1 || ym > 1)
  434.          {
  435.             fprintf(parmfile,"  video=%s", vidmde);
  436.             fprintf(parmfile," savename=frmig_%c%c\n", PAR_KEY(i), PAR_KEY(j));
  437.          }
  438.          fprintf(parmfile, "  }\n\n");
  439.       }
  440.       if(xm > 1 || ym > 1)
  441.          {
  442.          fprintf(fpbat,"Fractint makemig=%d/%d\n",xm,ym);
  443.          fprintf(fpbat,"Rem Simplgif fractmig.gif simplgif.gif  in case you need it\n");
  444.          fprintf(fpbat,":oops\n");
  445.          fclose(fpbat);
  446.          }
  447. /*******end here */
  448.  
  449.       if (gotinfile)
  450.       {                         /* copy the rest of the file */
  451.          while ((i = file_gets(buf, 255, infile)) == 0)
  452.             ; /* skip blanks */
  453.          while (i >= 0)
  454.          {
  455.             fputs(buf, parmfile);
  456.             fputc('\n', parmfile);
  457.             i = file_gets(buf, 255, infile);
  458.          }
  459.          fclose(infile);
  460.       }
  461.       fclose(parmfile);
  462.       if (gotinfile)
  463.       {                         /* replace the original file with the new */
  464.          unlink(CommandFile);   /* success assumed on these lines       */
  465.          rename(outname, CommandFile);  /* since we checked earlier with
  466.                                          * access */
  467.       }
  468.       break;
  469.    }
  470.    helpmode = oldhelpmode;
  471.    unstackscreen();
  472. }
  473. #ifdef C6
  474. #pragma optimize("e",on)  /* back to normal */
  475. #endif
  476.  
  477. static struct write_batch_data { /* buffer for parms to break lines nicely */
  478.    int len;
  479.    char *buf;
  480.    } *wbdata;
  481.  
  482. static void write_batch_parms(char *colorinf,int maxcolor)
  483. {
  484.    char far *saveshared;
  485.    int i,j,k;
  486.    double Xctr, Yctr;
  487.    LDBL Magnification;
  488.    double Xmagfactor, Rotation, Skew;
  489.    struct write_batch_data wb_data;
  490.    char *sptr;
  491.    char buf[81];
  492.    bf_t bfXctr=NULL, bfYctr=NULL;
  493.    int saved;
  494.    saved = save_stack();
  495.    if(bf_math)
  496.    {
  497.       bfXctr = alloc_stack(bflength+2);
  498.       bfYctr = alloc_stack(bflength+2);
  499.    }
  500.    wbdata = &wb_data;
  501.    wb_data.len = 0; /* force first parm to start on new line */
  502.  
  503.    /* Using near string boxx for buffer after saving to extraseg */
  504.  
  505.    saveshared = MK_FP(extraseg,0);
  506.    far_memcpy(saveshared,boxx,10000);
  507.    far_memset(boxx,0,10000);
  508.    wb_data.buf = (char *)boxx;
  509.  
  510.    if (display3d <= 0) { /* a fractal was generated */
  511.  
  512.       /****** fractal only parameters in this section *******/
  513.       put_parm(" reset"); /* the following should match code in ENCODER.C */
  514.       if (fractype == LYAPUNOV ||
  515.           fractype == FROTH || fractype == FROTHFP ||
  516.           fix_bof() || fix_period_bof() || use_old_distest || decomp[0] == 2)
  517.         put_parm("=%d",min(save_release,release));
  518.       else
  519.         put_parm("=%d",release);
  520.  
  521.       if (*(sptr = curfractalspecific->name) == '*') ++sptr;
  522.       put_parm( s_seqs,s_type,sptr);
  523.  
  524.       if (fractype == JULIBROT || fractype == JULIBROTFP)
  525.       {
  526.            put_parm(" %s=%.15g/%.15g/%.15g/%.15g",
  527.                s_julibrotfromto,mxmaxfp,mxminfp,mymaxfp,myminfp);
  528.          /* these rarely change */
  529.          if(originfp != 8 || heightfp != 7 || widthfp != 10 || distfp != 24
  530.                           || depthfp != 8 || zdots != 128)
  531.             put_parm(" %s=%d/%g/%g/%g/%g/%g",s_julibrot3d,
  532.                 zdots, originfp, depthfp, heightfp, widthfp,distfp);
  533.          if(eyesfp != 0)
  534.             put_parm(" %s=%g",s_julibroteyes,eyesfp);
  535.          if(neworbittype != JULIA)
  536.          {
  537.             char *name;
  538.             name = fractalspecific[neworbittype].name;
  539.             if(*name=='*')
  540.                name++;
  541.             put_parm(s_seqs,s_orbitname,name);
  542.          }
  543.          if(juli3Dmode != 0)
  544.             put_parm(s_seqs,s_3dmode,juli3Doptions[juli3Dmode]);
  545.       }
  546.       if (fractype == FORMULA || fractype == FFORMULA)
  547.       {
  548.      put_filename(s_formulafile,FormFileName);
  549.      put_parm( s_seqs,s_formulaname,FormName);
  550.       }
  551.       if (fractype == LSYSTEM)
  552.       {
  553.      put_filename(s_lfile,LFileName);
  554.      put_parm( s_seqs,s_lname,LName);
  555.       }
  556.       if (fractype == IFS || fractype == IFS3D)
  557.       {
  558.      put_filename(s_ifsfile,IFSFileName);
  559.      put_parm( s_seqs,s_ifs,IFSName);
  560.       }
  561.       if (fractype == INVERSEJULIA || fractype == INVERSEJULIAFP)
  562.      put_parm( " %s=%s/%s",s_miim,JIIMmethod[major_method], JIIMleftright[minor_method]);
  563.  
  564.       showtrig(buf); /* this function is in miscres.c */
  565.       if (buf[0])
  566.      put_parm(buf);
  567.  
  568.       if (usr_stdcalcmode != 'g')
  569.      put_parm(" %s=%c",s_passes,usr_stdcalcmode);
  570.  
  571.       if (usemag)
  572.       {
  573.          if (bf_math)
  574.          {
  575.             int digits;
  576.             cvtcentermagbf(bfXctr, bfYctr, &Magnification, &Xmagfactor, &Rotation, &Skew);
  577.             digits = getprecbf(MAXREZ);
  578.             put_parm(" %s=",s_centermag);
  579.             put_bf(0,bfXctr,digits);
  580.             put_bf(1,bfYctr,digits);
  581.          }
  582.          else /* !bf_math */
  583.          {
  584.             cvtcentermag(&Xctr, &Yctr, &Magnification, &Xmagfactor, &Rotation, &Skew);
  585.             put_parm(" %s=",s_centermag);
  586.             put_parm((delmin > 1000) ? "%g/%g" : "%+20.17lf/%+20.17lf", Xctr, Yctr);
  587.          }
  588. #ifdef USE_LONG_DOUBLE
  589.          put_parm("/%.7Lg",Magnification); /* precision of magnification not critical, but magnitude is */
  590. #else
  591.          put_parm("/%.7lg",Magnification); /* precision of magnification not critical, but magnitude is */
  592. #endif
  593.          /* round to avoid ugly decimals, precision here is not critical */
  594.          Xmagfactor = (long)(Xmagfactor * 1e5 + 0.5)/1e5;
  595.          Rotation   = (long)(Rotation   * 1e4 + 0.5)/1e4;
  596.          Skew       = (long)(Skew       * 1e4 + 0.5)/1e4;
  597.          if (Xmagfactor != 1 || Rotation != 0 || Skew != 0)
  598.          { /* only put what is necessary */
  599.             put_float(1,Xmagfactor,5);
  600.             if (Rotation != 0 || Skew != 0)
  601.             {
  602.                put_float(1,Rotation,4);
  603.                if (Skew != 0)
  604.                {
  605.                   put_float(1,Skew,4);
  606.                }
  607.             }
  608.          }
  609.       }
  610.       else /* not usemag */
  611.       {         
  612.          put_parm( " %s=",s_corners);
  613.          if(bf_math)
  614.          {
  615.             int digits;
  616.             digits = getprecbf(MAXREZ);
  617.             put_bf(0,bfxmin,digits);
  618.         put_bf(1,bfxmax,digits);
  619.         put_bf(1,bfymin,digits);
  620.         put_bf(1,bfymax,digits);
  621.         if (cmp_bf(bfx3rd,bfxmin) || cmp_bf(bfy3rd,bfymin)) 
  622.         {
  623.            put_bf(1,bfx3rd,digits);
  624.            put_bf(1,bfy3rd,digits);
  625.         }
  626.      }   
  627.          else 
  628.          {
  629.             int xdigits,ydigits;
  630.             xdigits = getprec(xxmin,xxmax,xx3rd);
  631.             ydigits = getprec(yymin,yymax,yy3rd);
  632.         put_float(0,xxmin,xdigits);
  633.         put_float(1,xxmax,xdigits);
  634.         put_float(1,yymin,ydigits);
  635.         put_float(1,yymax,ydigits);
  636.         if (xx3rd != xxmin || yy3rd != yymin) 
  637.         {
  638.            put_float(1,xx3rd,xdigits);
  639.            put_float(1,yy3rd,ydigits);
  640.         }
  641.          }
  642.       }   
  643.  
  644.       for(i = (MAXPARAMS-1); i >= 0; --i)
  645.           if(typehasparm((fractype==JULIBROT || fractype==JULIBROTFP)
  646.                           ?neworbittype:fractype,i) != NULL) break;
  647.  
  648.       if (i >= 0) {
  649.         if (fractype == CELLULAR)
  650.           put_parm(" %s=%.1f",s_params,param[0]);
  651.         else
  652.         {
  653. #ifdef USE_LONG_DOUBLE
  654.           if(debugflag == 750)
  655.              put_parm(" %s=%.17Lg",s_params,(long double)param[0]);
  656.           else
  657. #endif
  658.           put_parm(" %s=%.17g",s_params,param[0]);
  659.         }
  660.         for (j = 1; j <= i; ++j)
  661.         if (fractype == CELLULAR)
  662.           put_parm("/%.1f",param[j]);
  663.         else
  664.         {
  665. #ifdef USE_LONG_DOUBLE
  666.           if(debugflag == 750)
  667.              put_parm("/%.17Lg",(long double)param[j]);
  668.           else
  669. #endif
  670.           put_parm("/%.17g",param[j]);
  671.         }
  672.       }
  673.  
  674.       if(useinitorbit == 2)
  675.      put_parm( " %s=pixel",s_initorbit);
  676.       else if(useinitorbit == 1)
  677.      put_parm( " %s=%.15g/%.15g",s_initorbit,initorbit.x,initorbit.y);
  678.  
  679.       if (floatflag)
  680.      put_parm( " %s=y",s_float);
  681.  
  682.       if (maxit != 150)
  683.      put_parm(" %s=%ld",s_maxiter,maxit);
  684.  
  685.       if(bailout && (potflag == 0 || potparam[2] == 0.0))
  686.      put_parm(" %s=%ld",s_bailout,bailout);
  687.  
  688.       if(bailoutest != Mod && (potflag == 0 || potparam[2] == 0.0)) {
  689.      put_parm(" %s=",s_bailoutest);
  690.      if (bailoutest == Real)
  691.         put_parm( s_real);
  692.      else if (bailoutest == Imag)
  693.         put_parm(s_imag);
  694.      else if (bailoutest == Or)
  695.         put_parm(s_or);
  696.      else if (bailoutest == And)
  697.         put_parm(s_and);
  698.      else
  699.         put_parm(s_mod); /* default, just in case */
  700.       }
  701.       if(fillcolor != -1) {
  702.        put_parm(" %s=",s_fillcolor);
  703.     put_parm( "%d",fillcolor);
  704.       }
  705.       if (inside != 1) {
  706.      put_parm(" %s=",s_inside);
  707.      if (inside == -1)
  708.         put_parm( s_maxiter);
  709.      else if (inside == -59)
  710.         put_parm(s_zmag);
  711.      else if (inside == -60)
  712.         put_parm(s_bof60);
  713.      else if (inside == -61)
  714.         put_parm(s_bof61);
  715.      else if (inside == -100)
  716.         put_parm(s_epscross);
  717.      else if (inside == -101)
  718.         put_parm(s_startrail);
  719.      else if (inside == -102)
  720.         put_parm(s_period);
  721.      else
  722.         put_parm( "%d",inside);
  723.      }
  724.       if (outside != -1)
  725.       {
  726.      put_parm(" %s=",s_outside);
  727.      if (outside == -2)
  728.         put_parm(s_real);
  729.      else if (outside == -3)
  730.         put_parm(s_imag);
  731.      else if (outside == -4)
  732.         put_parm(s_mult);
  733.      else if (outside == -5)
  734.         put_parm(s_sum);
  735.      else if (outside == -6)
  736.         put_parm(s_atan);
  737.      else
  738.         put_parm( "%d",outside);
  739.       }
  740.  
  741.       if(LogFlag) {
  742.      put_parm( " %s=",s_logmap);
  743.      if(LogFlag == -1)
  744.         put_parm( "old");
  745.      else if(LogFlag == 1)
  746.         put_parm( s_yes);
  747.      else
  748.         put_parm( "%d", LogFlag);
  749.      }
  750.  
  751.       if (potflag) {
  752.        put_parm( " %s=%d/%g/%d",s_potential,
  753.            (int)potparam[0],potparam[1],(int)potparam[2]);
  754.        if(pot16bit)
  755.         put_parm( "/%s",s_16bit);
  756.      }
  757.       if (invert)
  758.      put_parm( " %s=%g/%g/%g",s_invert,
  759.          inversion[0], inversion[1], inversion[2]);
  760.       if (decomp[0])
  761.      put_parm( s_seqd,s_decomp, decomp[0]);
  762.       if (distest) {
  763.      put_parm( s_seqdddd,s_distest, distest, distestwidth,
  764.                  pseudox?pseudox:xdots,pseudoy?pseudoy:ydots);
  765.       }
  766.       if (old_demm_colors)
  767.      put_parm( s_olddemmcolors, old_demm_colors);
  768.       if (usr_biomorph != -1)
  769.      put_parm( s_seqd,s_biomorph, usr_biomorph);
  770.       if (finattract)
  771.      put_parm(" %s=y",s_finattract);
  772.  
  773.       if (forcesymmetry != 999) {
  774.          static FCODE msg[] = 
  775.             {"Regenerate before <b> to get correct symmetry"};
  776.          if(forcesymmetry == 1000)
  777.             stopmsg(0,msg);
  778.      put_parm( " %s=",s_symmetry);
  779.      if (forcesymmetry==XAXIS)
  780.         put_parm(s_xaxis);
  781.      else if(forcesymmetry==YAXIS)
  782.         put_parm(s_yaxis);
  783.      else if(forcesymmetry==XYAXIS)
  784.         put_parm(s_xyaxis);
  785.      else if(forcesymmetry==ORIGIN)
  786.         put_parm(s_origin);
  787.      else if(forcesymmetry==PI_SYM)
  788.         put_parm(s_pi);
  789.      else
  790.         put_parm(s_none);
  791.      }
  792.  
  793.       if (periodicitycheck != 1)
  794.      put_parm( s_seqd,s_periodicity,periodicitycheck);
  795.  
  796.       if (rflag)
  797.      put_parm( s_seqd,s_rseed,rseed);
  798.  
  799.       if (rangeslen) {
  800.      put_parm(" %s=",s_ranges);
  801.      i = 0;
  802.      while (i < rangeslen) {
  803.         if (i)
  804.            put_parm("/");
  805.         if (ranges[i] == -1) {
  806.            put_parm("-%d/",ranges[++i]);
  807.            ++i;
  808.            }
  809.         put_parm("%d",ranges[i++]);
  810.         }
  811.      }
  812.       }
  813.  
  814.    if (display3d >= 1) {
  815.       /***** 3d transform only parameters in this section *****/
  816.       if(display3d == 2)
  817.          put_parm( s_seqs,s_3d,s_overlay);
  818.       else
  819.       put_parm( s_seqs,s_3d,s_yes);
  820.       if (loaded3d == 0)
  821.      put_filename(s_filename,readname);
  822.       if (SPHERE) {
  823.      put_parm( " %s=y",s_sphere);
  824.      put_parm( s_seqdd,s_latitude, THETA1, THETA2);
  825.      put_parm( s_seqdd,s_longitude, PHI1, PHI2);
  826.      put_parm( s_seqd,s_radius, RADIUS);
  827.      }
  828.       put_parm( s_seqdd,s_scalexyz, XSCALE, YSCALE);
  829.       put_parm( s_seqd,s_roughness, ROUGH);
  830.       put_parm( s_seqd,s_waterline, WATERLINE);
  831.       if (FILLTYPE)
  832.      put_parm( s_seqd,s_filltype, FILLTYPE);
  833.       if (transparent[0] || transparent[1])
  834.      put_parm( s_seqdd,s_transparent, transparent[0],transparent[1]);
  835.       if (preview) {
  836.      put_parm( s_seqs,s_preview,s_yes);
  837.      if (showbox)
  838.         put_parm( s_seqs,s_showbox,s_yes);
  839.      put_parm( s_seqd,s_coarse,previewfactor);
  840.      }
  841.       if (RAY) {
  842.      put_parm( s_seqd,s_ray,RAY);
  843.      if (BRIEF)
  844.         put_parm(" %s=y",s_brief);
  845.      }
  846.       if (FILLTYPE > 4) {
  847.      put_parm( s_seqddd,s_lightsource, XLIGHT, YLIGHT, ZLIGHT);
  848.      if (LIGHTAVG)
  849.         put_parm( " %=%d",s_smoothing, LIGHTAVG);
  850.      }
  851.       if (RANDOMIZE)
  852.      put_parm( s_seqd,s_randomize,RANDOMIZE);
  853.       if (Targa_Out)
  854.      put_parm( " %s=y",s_fullcolor);
  855.       if (grayflag)
  856.      put_parm( " %s=y",s_usegrayscale);
  857.       if (Ambient)
  858.      put_parm( s_seqd,s_ambient,Ambient);
  859.       if (haze)
  860.      put_parm( s_seqd,s_haze,haze);
  861.       }
  862.  
  863.    if (display3d) {        /* universal 3d */
  864.       /***** common (fractal & transform) 3d parameters in this section *****/
  865.       if (!SPHERE || display3d < 0)
  866.      put_parm( s_seqddd,s_rotation, XROT, YROT, ZROT);
  867.       put_parm( s_seqd,s_perspective, ZVIEWER);
  868.       put_parm( s_seqdd,s_xyshift, XSHIFT, YSHIFT);
  869.       if(xtrans || ytrans)
  870.      put_parm( s_seqdd,s_xyadjust,xtrans,ytrans);
  871.       if(glassestype) {
  872.      put_parm( s_seqd,s_stereo,glassestype);
  873.      put_parm( s_seqd,s_interocular,eyeseparation);
  874.      put_parm( s_seqd,s_converge,xadjust);
  875.      put_parm( " %s=%d/%d/%d/%d",s_crop,
  876.          red_crop_left,red_crop_right,blue_crop_left,blue_crop_right);
  877.      put_parm( s_seqdd,s_bright,
  878.          red_bright,blue_bright);
  879.      }
  880.       }
  881.  
  882.    /***** universal parameters in this section *****/
  883.  
  884.    if(viewwindow == 1)
  885.    {
  886.       put_parm(" %s=%g/%g",s_viewwindows,viewreduction,finalaspectratio);
  887.       if(viewcrop)
  888.          put_parm("/%s",s_yes);
  889.       else
  890.          put_parm("/%s",s_no);
  891.       put_parm("/%d/%d",viewxdots,viewydots);
  892.    }
  893.    if (*colorinf != 'n') {
  894.       put_parm(" %s=",s_colors);
  895.       if (*colorinf == '@')
  896.      put_parm(colorinf);
  897.       else {
  898.      int curc,scanc,force,diffmag = -1;
  899.      int delta,diff1[4][3],diff2[4][3];
  900.      curc = force = 0;
  901.      for(;;) {
  902.         /* emit color in rgb 3 char encoded form */
  903.         for (j = 0; j < 3; ++j) {
  904.            if ((k = dacbox[curc][j]) < 10) k += '0';
  905.            else if (k < 36)            k += ('A' - 10);
  906.            else                   k += ('_' - 36);
  907.            buf[j] = (char)k;
  908.            }
  909.         buf[3] = 0;
  910.         put_parm(buf);
  911.         if (++curc >= maxcolor)     /* quit if done last color */
  912.            break;
  913.         /* Next a P Branderhorst special, a tricky scan for smooth-shaded
  914.            ranges which can be written as <nn> to compress .par file entry.
  915.            Method used is to check net change in each color value over
  916.            spans of 2 to 5 color numbers.  First time for each span size
  917.            the value change is noted.  After first time the change is
  918.            checked against noted change.  First time it differs, a
  919.            a difference of 1 is tolerated and noted as an alternate
  920.            acceptable change.  When change is not one of the tolerated
  921.            values, loop exits. */
  922.         if (force) {
  923.            --force;
  924.            continue;
  925.            }
  926.         scanc = curc;
  927.         while (scanc < maxcolor) {     /* scan while same diff to next */
  928.            if ((i = scanc - curc) > 3) /* check spans up to 4 steps */
  929.           i = 3;
  930.            for (k = 0; k <= i; ++k) {
  931.           for (j = 0; j < 3; ++j) { /* check pattern of chg per color */
  932.              delta = (int)dacbox[scanc][j] - (int)dacbox[scanc-k-1][j];
  933.              if (k == scanc - curc)
  934.             diff1[k][j] = diff2[k][j] = delta;
  935.              else
  936.             if (delta != diff1[k][j] && delta != diff2[k][j]) {
  937.                diffmag = abs(delta - diff1[k][j]);
  938.                if (diff1[k][j] != diff2[k][j] || diffmag != 1)
  939.                   break;
  940.                diff2[k][j] = delta;
  941.                }
  942.              }
  943.           if (j < 3) break; /* must've exited from inner loop above */
  944.           }
  945.            if (k <= i) break;   /* must've exited from inner loop above */
  946.            ++scanc;
  947.            }
  948.         /* now scanc-1 is next color which must be written explicitly */
  949.         if (scanc - curc > 2) { /* good, we have a shaded range */
  950.            if (scanc != maxcolor) {
  951.                   static FCODE msg[] = {"Tell Tim Wegner to check diffmag MISCOVL.C"};
  952.                   if(diffmag < 0) stopmsg(0,msg);
  953.           if (diffmag < 3) {  /* not a sharp slope change? */
  954.              force = 2;       /* force more between ranges, to stop  */
  955.              --scanc;          /* "drift" when load/store/load/store/ */
  956.              }
  957.           if (k) {          /* more of the same             */
  958.              force += k;
  959.              --scanc;
  960.              }
  961.           }
  962.            if (--scanc - curc > 1) {
  963.           put_parm("<%d>",scanc-curc);
  964.           curc = scanc;
  965.           }
  966.            else           /* changed our mind */
  967.           force = 0;
  968.            }
  969.         }
  970.      }
  971.       }
  972.  
  973.    if (rotate_lo != 1 || rotate_hi != 255)
  974.       put_parm( s_seqdd,s_cyclerange,rotate_lo,rotate_hi);
  975.  
  976.    while (wbdata->len) /* flush the buffer */
  977.       put_parm_line();
  978.    /* restore previous boxx data from extraseg */
  979.    far_memcpy(boxx, saveshared, 10000);
  980.    restore_stack(saved);
  981. }
  982.  
  983. static void put_filename(char *keyword,char *fname)
  984. {
  985.    char *p;
  986.    if (*fname && !endswithslash(fname)) {
  987.       if ((p = strrchr(fname, SLASHC)) != NULL)
  988.      if (*(fname = p+1) == 0) return;
  989.       put_parm(s_seqs,keyword,fname);
  990.       }
  991. }
  992.  
  993. #ifndef XFRACT
  994. static void put_parm(char *parm,...)
  995. #else
  996. static void put_parm(va_alist)
  997. va_dcl
  998. #endif
  999. {
  1000.    char *bufptr;
  1001.    va_list args;
  1002.  
  1003. #ifndef XFRACT
  1004.    va_start(args,parm);
  1005. #else
  1006.    char * parm;
  1007.  
  1008.    va_start(args);
  1009.    parm = va_arg(args,char *);
  1010. #endif
  1011.    if (*parm == ' '             /* starting a new parm */
  1012.      && wbdata->len == 0)    /* skip leading space */
  1013.       ++parm;
  1014.    bufptr = wbdata->buf + wbdata->len;
  1015.    vsprintf(bufptr,parm,args);
  1016.    while (*(bufptr++))
  1017.       ++wbdata->len;
  1018.    while (wbdata->len > 200)
  1019.       put_parm_line();
  1020. }
  1021.  
  1022. #define NICELINELEN 68
  1023. #define MAXLINELEN  72
  1024.  
  1025. static void put_parm_line()
  1026. {
  1027.    int len,c;
  1028.    if ((len = wbdata->len) > NICELINELEN) {
  1029.       len = NICELINELEN+1;
  1030.       while (--len != 0 && wbdata->buf[len] != ' ') { }
  1031.       if (len == 0) {
  1032.      len = NICELINELEN-1;
  1033.      while (++len < MAXLINELEN
  1034.        && wbdata->buf[len] && wbdata->buf[len] != ' ') { }
  1035.      }
  1036.       }
  1037.    c = wbdata->buf[len];
  1038.    wbdata->buf[len] = 0;
  1039.    fputs("  ",parmfile);
  1040.    fputs(wbdata->buf,parmfile);
  1041.    if (c && c != ' ')
  1042.       fputc('\\',parmfile);
  1043.    fputc('\n',parmfile);
  1044.    if ((wbdata->buf[len] = (char)c) == ' ')
  1045.       ++len;
  1046.    wbdata->len -= len;
  1047.    strcpy(wbdata->buf,wbdata->buf+len);
  1048. }
  1049.  
  1050. int getprecbf_mag()
  1051. {
  1052.    double Xmagfactor, Rotation, Skew;
  1053.    LDBL Magnification;
  1054.    bf_t bXctr, bYctr;
  1055.    int saved,dec;
  1056.  
  1057.    saved = save_stack();
  1058.    bXctr            = alloc_stack(bflength+2);
  1059.    bYctr            = alloc_stack(bflength+2);
  1060.    /* this is just to find Magnification */
  1061.    cvtcentermagbf(bXctr, bYctr, &Magnification, &Xmagfactor, &Rotation, &Skew);
  1062.    restore_stack(saved);
  1063.  
  1064.    /* I don't know if this is portable, but something needs to */
  1065.    /* be used in case compiler's LDBL_MAX is not big enough    */
  1066.    if (Magnification > LDBL_MAX || Magnification < -LDBL_MAX)
  1067.       return(-1);
  1068.  
  1069.    dec = getpower10(Magnification) + 4; /* 4 digits of padding sounds good */
  1070.    return(dec);
  1071. }   
  1072.  
  1073. static int getprec(double a,double b,double c)
  1074. {
  1075.    double diff,temp;
  1076.    int digits;
  1077.    double highv = 1.0E20;
  1078.    if ((diff = fabs(a - b)) == 0.0) diff = highv;
  1079.    if ((temp = fabs(a - c)) == 0.0) temp = highv;
  1080.    if (temp < diff) diff = temp;
  1081.    if ((temp = fabs(b - c)) == 0.0) temp = highv;
  1082.    if (temp < diff) diff = temp;
  1083.    digits = 7;
  1084.    if(debugflag >= 700 && debugflag < 720 )
  1085.       digits =  debugflag - 700;
  1086.    while (diff < 1.0 && digits <= DBL_DIG+1) {
  1087.       diff *= 10;
  1088.       ++digits;
  1089.       }
  1090.    return(digits);
  1091. }
  1092.  
  1093. /* This function calculates the precision needed to distiguish adjacent
  1094.    pixels at Fractint's maximum resolution of MAXPIXELS by MAXPIXELS 
  1095.    (if rez==MAXREZ) or at current resolution (if rez==CURRENTREZ)    */
  1096. int getprecbf(int rezflag)
  1097. {
  1098.    bf_t del1,del2, one, bfxxdel, bfxxdel2, bfyydel, bfyydel2;
  1099.    int digits,dec;
  1100.    int saved;
  1101.    int rez;
  1102.    saved    = save_stack();
  1103.    del1     = alloc_stack(bflength+2);
  1104.    del2     = alloc_stack(bflength+2);
  1105.    one      = alloc_stack(bflength+2);
  1106.    bfxxdel   = alloc_stack(bflength+2);
  1107.    bfxxdel2  = alloc_stack(bflength+2);
  1108.    bfyydel   = alloc_stack(bflength+2);
  1109.    bfyydel2  = alloc_stack(bflength+2);
  1110.    floattobf(one,1.0);
  1111.    if(rezflag == MAXREZ)
  1112.       rez = MAXPIXELS -1;
  1113.    else
  1114.       rez = xdots-1;   
  1115.  
  1116.    /* bfxxdel = (bfxmax - bfx3rd)/(xdots-1) */
  1117.    sub_bf(bfxxdel, bfxmax, bfx3rd);
  1118.    div_a_bf_int(bfxxdel, (U16)rez);
  1119.  
  1120.    /* bfyydel2 = (bfy3rd - bfymin)/(xdots-1) */
  1121.    sub_bf(bfyydel2, bfy3rd, bfymin);
  1122.    div_a_bf_int(bfyydel2, (U16)rez);
  1123.  
  1124.    if(rezflag == CURRENTREZ)
  1125.       rez = ydots-1;   
  1126.  
  1127.    /* bfyydel = (bfymax - bfy3rd)/(ydots-1) */
  1128.    sub_bf(bfyydel, bfymax, bfy3rd);
  1129.    div_a_bf_int(bfyydel, (U16)rez);
  1130.  
  1131.    /* bfxxdel2 = (bfx3rd - bfxmin)/(ydots-1) */
  1132.    sub_bf(bfxxdel2, bfx3rd, bfxmin);
  1133.    div_a_bf_int(bfxxdel2, (U16)rez);
  1134.  
  1135.    abs_a_bf(add_bf(del1,bfxxdel,bfxxdel2));
  1136.    abs_a_bf(add_bf(del2,bfyydel,bfyydel2));
  1137.    if(cmp_bf(del2,del1) < 0)
  1138.        copy_bf(del1, del2);
  1139.    if(cmp_bf(del1,clear_bf(del2)) == 0)
  1140.    {
  1141.       restore_stack(saved);
  1142.       return(-1);
  1143.    }
  1144.    digits = 1;
  1145.    while(cmp_bf(del1,one) < 0)
  1146.    {
  1147.       digits++;
  1148.       mult_a_bf_int(del1,10);
  1149.    }   
  1150.    digits = max(digits,3);
  1151.    restore_stack(saved);
  1152.    dec = getprecbf_mag();
  1153.    return(max(digits,dec));
  1154. }
  1155.  
  1156. /* This function calculates the precision needed to distiguish adjacent
  1157.    pixels at Fractint's maximum resolution of MAXPIXELS by MAXPIXELS 
  1158.    (if rez==MAXREZ) or at current resolution (if rez==CURRENTREZ)    */
  1159. int getprecdbl(int rezflag)
  1160. {
  1161.    LDBL del1,del2, xdel, xdel2, ydel, ydel2;
  1162.    int digits;
  1163.    LDBL rez;
  1164.    if(rezflag == MAXREZ)
  1165.       rez = MAXPIXELS -1;
  1166.    else
  1167.       rez = xdots-1;   
  1168.       
  1169.    xdel =  ((LDBL)xxmax - (LDBL)xx3rd)/rez;
  1170.    ydel2 = ((LDBL)yy3rd - (LDBL)yymin)/rez;
  1171.  
  1172.    if(rezflag == CURRENTREZ)
  1173.       rez = ydots-1;   
  1174.  
  1175.    ydel = ((LDBL)yymax - (LDBL)yy3rd)/rez;
  1176.    xdel2 = ((LDBL)xx3rd - (LDBL)xxmin)/rez;
  1177.  
  1178.    del1 = fabsl(xdel) + fabsl(xdel2);
  1179.    del2 = fabsl(ydel) + fabsl(ydel2);
  1180.    if(del2 < del1)
  1181.        del1 = del2;
  1182.    if(del1 == 0)
  1183.    {
  1184. #ifdef DEBUG
  1185.       showcornersdbl("getprecdbl");
  1186. #endif
  1187.       return(-1);
  1188.    }
  1189.    digits = 1;
  1190.    while(del1 < 1.0)
  1191.    {
  1192.       digits++;
  1193.       del1 *= 10;
  1194.    }   
  1195.    digits = max(digits,3);
  1196.    return(digits);
  1197. }
  1198.  
  1199. static void put_float(int slash,double fnum,int prec)
  1200. {  char buf[40];
  1201.    char *bptr, *dptr;
  1202.    bptr = buf;
  1203.    if (slash)
  1204.       *(bptr++) = '/';
  1205. /*   sprintf(bptr,"%1.*f",prec,fnum); */
  1206. #ifdef USE_LONG_DOUBLE
  1207.      /* Idea of long double cast is to squeeze out another digit or two
  1208.         which might be needed (we have found cases where this digit makes
  1209.         a difference.) But lets not do this at lower precision */
  1210.      if(prec > 15) 
  1211.         sprintf(bptr,"%1.*Lg",prec,(long double)fnum);
  1212.      else
  1213. #endif
  1214.      sprintf(bptr,"%1.*g",prec,(double)fnum);
  1215.  
  1216.    if ((dptr = strchr(bptr,'.')) != 0) {
  1217.       ++dptr;
  1218.       bptr = buf + strlen(buf);
  1219.       while (--bptr > dptr && *bptr == '0')
  1220.      *bptr = 0;
  1221.       }
  1222.    put_parm(buf);
  1223. }
  1224.  
  1225. static void put_bf(int slash,bf_t r, int prec)
  1226. {  
  1227.    char *buf; /* "/-1.xxxxxxE-1234" */
  1228.    char *bptr, *dptr, *exptr;
  1229.    /* buf = malloc(decimals+11); */
  1230.    buf = wbdata->buf+5000;  /* end of use suffix buffer, 5000 bytes safe */
  1231.    bptr = buf;
  1232.    if (slash)
  1233.       *(bptr++) = '/';
  1234.    bftostr(bptr, prec, r);
  1235.  
  1236.    if ((dptr = strchr(bptr,'.')) != 0) {
  1237.       ++dptr;
  1238.       if ((exptr = strchr(buf,'e')) !=0)  /* scientific notation with 'e'? */
  1239.          bptr = exptr;
  1240.       else
  1241.          bptr = buf + strlen(buf);
  1242.       while (--bptr > dptr && *bptr == '0')
  1243.      *bptr = 0;
  1244.       if(exptr && bptr < exptr -1) 
  1245.         strcat(buf,exptr);
  1246.    }     
  1247.    put_parm(buf);
  1248. }
  1249.  
  1250. #ifndef XFRACT
  1251. #include <direct.h>
  1252. void shell_to_dos()
  1253. {
  1254.    int drv;
  1255.    char *comspec;
  1256.    char curdir[80],*s;
  1257.    if ((comspec = getenv("COMSPEC")) == NULL)
  1258.       printf("Cannot find COMMAND.COM.\n");
  1259.    else {
  1260.       putenv("PROMPT='EXIT' returns to FRACTINT.$_$p$g");
  1261.       s = getcwd(curdir,100);
  1262.       drv = _getdrive();
  1263.       spawnl(P_WAIT, comspec, NULL);
  1264.       if(drv)
  1265.          _chdrive(drv);
  1266.       if(s)
  1267.          chdir(s);
  1268.       }
  1269. }
  1270.  
  1271. size_t showstack(void)
  1272. {
  1273. #ifdef _MSC_VER
  1274. #if (_MSC_VER == 700 || _MSC_VER == 800)
  1275.    return(_stackavail());
  1276. /* add other implementations here */
  1277. #elif (_MSC_VER == 600)
  1278.    return(stackavail());
  1279. #endif
  1280. #else   
  1281.    return(-1);
  1282. #endif
  1283. }
  1284.  
  1285. long fr_farfree(void)
  1286. {
  1287.    long j,j2; 
  1288.    BYTE huge *fartempptr;
  1289.    j = 0;
  1290.    j2 = 0x80000L;
  1291.    while ((j2 >>= 1) != 0)
  1292.       if ((fartempptr = (BYTE huge *)farmemalloc(j+j2)) != NULL) {
  1293.      farmemfree((void far*)fartempptr);
  1294.      j += j2;
  1295.      }
  1296.    return(j);
  1297. }
  1298.  
  1299. void showfreemem(void)
  1300. {
  1301.    char *tempptr;
  1302.    unsigned i,i2;
  1303.  
  1304.    char adapter_name[8];      /* entry lenth from VIDEO.ASM */
  1305.    char *adapter_ptr;
  1306.  
  1307.    printf("\n CPU type: %d  FPU type: %d  IIT FPU: %d  Video: %d",
  1308.       cpu, fpu, iit, video_type);
  1309.          
  1310.    adapter_ptr = &supervga_list;
  1311.    
  1312.    for(i = 0 ; ; i++) {        /* find the SuperVGA entry */
  1313.        int j;
  1314.        memcpy(adapter_name , adapter_ptr, 8);
  1315.        adapter_ptr += 8;
  1316.        if (adapter_name[0] == ' ') break;    /* end-of-the-list */
  1317.        if (adapter_name[6] == 0) continue;    /* not our adapter */
  1318.        adapter_name[6] = ' ';
  1319.        for (j = 0; j < 8; j++)
  1320.            if(adapter_name[j] == ' ')
  1321.                adapter_name[j] = 0;
  1322.        printf("  Video chip: %d (%s)",i+1,adapter_name);
  1323.        }
  1324.    printf("\n\n");
  1325.  
  1326.    i = 0;
  1327.    i2 = 0x8000;
  1328.    while ((i2 >>= 1) != 0)
  1329.       if ((tempptr = malloc(i+i2)) != NULL) {
  1330.      free(tempptr);
  1331.      i += i2;
  1332.      }
  1333.    printf(" %d NEAR bytes free \n", i);
  1334.  
  1335.    printf(" %ld FAR bytes free ", fr_farfree());
  1336.    {
  1337.       size_t stack;
  1338.       stack = showstack();
  1339. /*      if(stack >= 0) */ /* stack is unsigned */
  1340.          printf("\n %u STACK bytes free",stack);
  1341.    }
  1342.    printf("\n %ld used by HISTORY structure",
  1343.       sizeof(HISTORY)*(unsigned long)maxhistory);
  1344.    printf("\n %d video table used",showvidlength());
  1345.    printf("\n\n %Fs...\n",s_pressanykeytocontinue);
  1346.    getakey();
  1347. }
  1348. #endif
  1349.  
  1350. edit_text_colors()
  1351. {
  1352.    int save_debugflag,save_lookatmouse;
  1353.    int row,col,bkgrd;
  1354.    int rowf,colf,rowt,colt;
  1355.    char far *vidmem;
  1356.    char far *savescreen;
  1357.    char far *farp1; char far *farp2;
  1358.    int i,j,k;
  1359.    save_debugflag = debugflag;
  1360.    save_lookatmouse = lookatmouse;
  1361.    debugflag = 0;   /* don't get called recursively */
  1362.    lookatmouse = 2; /* text mouse sensitivity */
  1363.    row = col = bkgrd = rowt = rowf = colt = colf = 0;
  1364.    vidmem = MK_FP(0xB800,0);
  1365.    for(;;) {
  1366.       if (row < 0)  row = 0;
  1367.       if (row > 24) row = 24;
  1368.       if (col < 0)  col = 0;
  1369.       if (col > 79) col = 79;
  1370.       movecursor(row,col);
  1371.       i = getakey();
  1372.       if (i >= 'a' && i <= 'z') i -= 32; /* uppercase */
  1373.       switch (i) {
  1374.      case 27: /* esc */
  1375.         debugflag = save_debugflag;
  1376.         lookatmouse = save_lookatmouse;
  1377.         movecursor(25,80);
  1378.         return 0;
  1379.      case '/':
  1380.         farp1 = savescreen = farmemalloc(4000L);
  1381.         farp2 = vidmem;
  1382.         for (i = 0; i < 4000; ++i) { /* save and blank */
  1383.            *(farp1++) = *farp2;
  1384.            *(farp2++) = 0;
  1385.            }
  1386.         for (i = 0; i < 8; ++i)      /* 8 bkgrd attrs */
  1387.            for (j = 0; j < 16; ++j) { /* 16 fgrd attrs */
  1388.           k = i*16 + j;
  1389.           farp1 = vidmem + i*320 + j*10;
  1390.           *(farp1++) = ' '; *(farp1++) = (char)k;
  1391.           *(farp1++) = (char)(i+'0'); *(farp1++) = (char)k;
  1392.           *(farp1++) = (char)((j < 10) ? j+'0' : j+'A'-10); *(farp1++) = (char)k;
  1393.           *(farp1++) = ' '; *(farp1++) = (char)k;
  1394.           }
  1395.         getakey();
  1396.         farp1 = vidmem;
  1397.         farp2 = savescreen;
  1398.         for (i = 0; i < 4000; ++i) /* restore */
  1399.            *(farp1++) = *(farp2++);
  1400.         farmemfree(savescreen);
  1401.         break;
  1402.      case ',':
  1403.         rowf = row; colf = col; break;
  1404.      case '.':
  1405.         rowt = row; colt = col; break;
  1406.      case ' ': /* next color is background */
  1407.         bkgrd = 1; break;
  1408.      case 1075: /* cursor left  */
  1409.         --col; break;
  1410.      case 1077: /* cursor right */
  1411.         ++col; break;
  1412.      case 1072: /* cursor up    */
  1413.         --row; break;
  1414.      case 1080: /* cursor down  */
  1415.         ++row; break;
  1416.      case 13:   /* enter */
  1417.         *(vidmem + row*160 + col*2) = (char)getakey();
  1418.         break;
  1419.      default:
  1420.         if (i >= '0' && i <= '9')      i -= '0';
  1421.         else if (i >= 'A' && i <= 'F') i -= 'A'-10;
  1422.         else break;
  1423.         for (j = rowf; j <= rowt; ++j)
  1424.            for (k = colf; k <= colt; ++k) {
  1425.           farp1 = vidmem + j*160 + k*2 + 1;
  1426.           if (bkgrd) *farp1 = (char)((*farp1 & 15) + i * 16);
  1427.           else         *farp1 = (char)((*farp1 & 0xf0) + i);
  1428.           }
  1429.         bkgrd = 0;
  1430.      }
  1431.       }
  1432. }
  1433.  
  1434. static int *entsptr;
  1435. static int modes_changed;
  1436.  
  1437. int select_video_mode(int curmode)
  1438. {
  1439.    static FCODE o_hdg2[]={"key...name......................xdot.ydot.colr.comment.................."};
  1440.    static FCODE o_hdg1[]={"Select Video Mode"};
  1441.    char hdg2[sizeof(o_hdg2)];
  1442.    char hdg1[sizeof(o_hdg1)];
  1443.    
  1444.    int entnums[MAXVIDEOMODES];
  1445.    int attributes[MAXVIDEOMODES];
  1446.    int i,j,k,ret;
  1447.    int oldtabmode,oldhelpmode;
  1448.  
  1449.    load_fractint_cfg(0);    /* load fractint.cfg to extraseg */
  1450.  
  1451.    far_strcpy(hdg1,o_hdg1);
  1452.    far_strcpy(hdg2,o_hdg2);
  1453.  
  1454.    for (i = 0; i < vidtbllen; ++i) { /* init tables */
  1455.       entnums[i] = i;
  1456.       attributes[i] = 1;
  1457.       }
  1458.    entsptr = entnums;        /* for indirectly called subroutines */
  1459.  
  1460.    qsort(entnums,vidtbllen,sizeof(entnums[0]),entcompare); /* sort modes */
  1461.  
  1462.    /* pick default mode */
  1463.    if (curmode < 0) {
  1464.       switch (video_type) { /* set up a reasonable default (we hope) */
  1465.      case 1:  videoentry.videomodeax = 8;    /* hgc */
  1466.           videoentry.colors = 2;
  1467.           break;
  1468.      case 2:  videoentry.videomodeax = 4;    /* cga */
  1469.           videoentry.colors = 4;
  1470.           break;
  1471.      case 3:  videoentry.videomodeax = 16;    /* ega */
  1472.           videoentry.colors = 16;
  1473.           if (mode7text) {        /* egamono */
  1474.              videoentry.videomodeax = 15;
  1475.              videoentry.colors = 2;
  1476.              }
  1477.           break;
  1478.      default: videoentry.videomodeax = 19;    /* mcga/vga? */
  1479.           videoentry.colors = 256;
  1480.           break;
  1481.      }
  1482.       }
  1483.    else
  1484.       far_memcpy((char far *)&videoentry,(char far *)&videotable[curmode],
  1485.          sizeof(videoentry));
  1486. #ifndef XFRACT
  1487.    for (i = 0; i < vidtbllen; ++i) { /* find default mode */
  1488.       if ( videoentry.videomodeax == vidtbl[entnums[i]].videomodeax
  1489.     && videoentry.colors      == vidtbl[entnums[i]].colors
  1490.     && (curmode < 0
  1491.         || far_memcmp((char far *)&videoentry,(char far *)&vidtbl[entnums[i]],
  1492.               sizeof(videoentry)) == 0))
  1493.      break;
  1494.       }
  1495.    if (i >= vidtbllen) /* no match, default to first entry */
  1496.       i = 0;
  1497.  
  1498.    oldtabmode = tabmode;
  1499.    oldhelpmode = helpmode;
  1500.    modes_changed = 0;
  1501.    tabmode = 0;
  1502.    helpmode = HELPVIDSEL;
  1503.    i = fullscreen_choice(CHOICEHELP,hdg1,hdg2,NULL,vidtbllen,NULL,attributes,
  1504.                          1,16,72,i,format_vid_table,NULL,NULL,check_modekey);
  1505.    tabmode = oldtabmode;
  1506.    helpmode = oldhelpmode;
  1507.    if (i == -1) {
  1508.    static FCODE msg[]={"Save new function key assignments or cancel changes?"};
  1509.       if (modes_changed /* update fractint.cfg for new key assignments */
  1510.     && badconfig == 0
  1511.     && stopmsg(22,msg) == 0)
  1512.      update_fractint_cfg();
  1513.       return(-1);
  1514.       }
  1515.    if (i < 0)    /* picked by function key */
  1516.       i = -1 - i;
  1517.    else     /* picked by Enter key */
  1518.       i = entnums[i];
  1519. #endif
  1520.    far_memcpy((char far *)&videoentry,(char far *)&vidtbl[i],
  1521.           sizeof(videoentry));  /* the selected entry now in videoentry */
  1522.  
  1523. #ifndef XFRACT
  1524.    /* copy fractint.cfg table to resident table, note selected entry */
  1525.    j = k = 0;
  1526.    far_memset((char far *)videotable,0,sizeof(*vidtbl)*MAXVIDEOTABLE);
  1527.    for (i = 0; i < vidtbllen; ++i) {
  1528.       if (vidtbl[i].keynum > 0) {
  1529.      far_memcpy((char far *)&videotable[j],(char far *)&vidtbl[i],
  1530.             sizeof(*vidtbl));
  1531.      if (far_memcmp((char far *)&videoentry,(char far *)&vidtbl[i],
  1532.             sizeof(videoentry)) == 0)
  1533.         k = vidtbl[i].keynum;
  1534.      if (++j >= MAXVIDEOTABLE-1)
  1535.         break;
  1536.      }
  1537.       }
  1538. #else
  1539.     k = vidtbl[0].keynum;
  1540. #endif
  1541.    if ((ret = k) == 0) { /* selected entry not a copied (assigned to key) one */
  1542.       far_memcpy((char far *)&videotable[MAXVIDEOTABLE-1],
  1543.          (char far *)&videoentry,sizeof(*vidtbl));
  1544.       ret = 1400; /* special value for check_vidmode_key */
  1545.       }
  1546.  
  1547.    if (modes_changed /* update fractint.cfg for new key assignments */
  1548.      && badconfig == 0)
  1549.       update_fractint_cfg();
  1550.  
  1551.    return(ret);
  1552. }
  1553.  
  1554. void format_vid_table(int choice,char *buf)
  1555. {
  1556.    char kname[5];
  1557.    char biosflag;
  1558.    far_memcpy((char far *)&videoentry,(char far *)&vidtbl[entsptr[choice]],
  1559.           sizeof(videoentry));
  1560.    vidmode_keyname(videoentry.keynum,kname);
  1561.    biosflag = (char)((videoentry.dotmode % 100 == 1) ? 'B' : ' ');
  1562.    sprintf(buf,"%-5s %-25s %4d %4d %3d%c %-25s",  /* 72 chars */
  1563.        kname, videoentry.name, videoentry.xdots, videoentry.ydots,
  1564.        videoentry.colors, biosflag, videoentry.comment);
  1565. }
  1566.  
  1567. static int check_modekey(int curkey,int choice)
  1568. {
  1569.    int i,j,k,ret;
  1570.    if ((i = check_vidmode_key(1,curkey)) >= 0)
  1571.       return(-1-i);
  1572.    i = entsptr[choice];
  1573.    ret = 0;
  1574.    if ( (curkey == '-' || curkey == '+')
  1575.      && (vidtbl[i].keynum == 0 || vidtbl[i].keynum >= 1084)) {
  1576.       static FCODE msg[]={"Missing or bad FRACTINT.CFG file. Can't reassign keys."};
  1577.       if (badconfig)
  1578.      stopmsg(0,msg);
  1579.       else {
  1580.      if (curkey == '-') {                   /* deassign key? */
  1581.         if (vidtbl[i].keynum >= 1084) {
  1582.            vidtbl[i].keynum = 0;
  1583.            modes_changed = 1;
  1584.            }
  1585.         }
  1586.      else {                 /* assign key? */
  1587.         j = getakeynohelp();
  1588.         if (j >= 1084 && j <= 1113) {
  1589.            for (k = 0; k < vidtbllen; ++k) {
  1590.           if (vidtbl[k].keynum == j) {
  1591.              vidtbl[k].keynum = 0;
  1592.              ret = -1; /* force redisplay */
  1593.              }
  1594.           }
  1595.            vidtbl[i].keynum = j;
  1596.            modes_changed = 1;
  1597.            }
  1598.         }
  1599.      }
  1600.       }
  1601.    return(ret);
  1602. }
  1603.  
  1604. static int entcompare(VOIDCONSTPTR p1,VOIDCONSTPTR p2)
  1605. {
  1606.    int i,j;
  1607.    if ((i = vidtbl[*((int *)p1)].keynum) == 0) i = 9999;
  1608.    if ((j = vidtbl[*((int *)p2)].keynum) == 0) j = 9999;
  1609.    if (i < j || (i == j && *((int *)p1) < *((int *)p2)))
  1610.       return(-1);
  1611.    return(1);
  1612. }
  1613.  
  1614. static void update_fractint_cfg()
  1615. {
  1616. #ifndef XFRACT
  1617.    char cfgname[100],outname[100],buf[121],kname[5];
  1618.    FILE *cfgfile,*outfile;
  1619.    int far *cfglinenums;
  1620.    int i,j,linenum,nextlinenum,nextmode;
  1621.    struct videoinfo vident;
  1622.  
  1623.    findpath("fractint.cfg",cfgname);
  1624.  
  1625.    if (access(cfgname,6)) {
  1626.       sprintf(buf,s_cantwrite,cfgname);
  1627.       stopmsg(0,buf);
  1628.       return;
  1629.       }
  1630.    strcpy(outname,cfgname);
  1631.    i = strlen(outname);
  1632.    while (--i >= 0 && outname[i] != SLASHC)
  1633.    outname[i] = 0;
  1634.    strcat(outname,"fractint.tmp");
  1635.    if ((outfile = fopen(outname,"w")) == NULL) {
  1636.       sprintf(buf,s_cantcreate,outname);
  1637.       stopmsg(0,buf);
  1638.       return;
  1639.       }
  1640.    cfgfile = fopen(cfgname,"r");
  1641.  
  1642.    cfglinenums = (int far *)(&vidtbl[MAXVIDEOMODES]);
  1643.    linenum = nextmode = 0;
  1644.    nextlinenum = cfglinenums[0];
  1645.    while (fgets(buf,120,cfgfile)) {
  1646.       ++linenum;
  1647.       if (linenum == nextlinenum) { /* replace this line */
  1648.      far_memcpy((char far *)&vident,(char far *)&vidtbl[nextmode],
  1649.             sizeof(videoentry));
  1650.      vidmode_keyname(vident.keynum,kname);
  1651.      strcpy(buf,vident.name);
  1652.      i = strlen(buf);
  1653.      while (i && buf[i-1] == ' ') /* strip trailing spaces to compress */
  1654.         --i;
  1655.      j = i + 5;
  1656.      while (j < 32) {        /* tab to column 33 */
  1657.         buf[i++] = '\t';
  1658.         j += 8;
  1659.         }
  1660.      buf[i] = 0;
  1661.      fprintf(outfile,"%-4s,%s,%4x,%4x,%4x,%4x,%4d,%4d,%4d,%3d,%s\n",
  1662.         kname,
  1663.         buf,
  1664.         vident.videomodeax,
  1665.         vident.videomodebx,
  1666.         vident.videomodecx,
  1667.         vident.videomodedx,
  1668.         vident.dotmode,
  1669.         vident.xdots,
  1670.         vident.ydots,
  1671.         vident.colors,
  1672.         vident.comment);
  1673.      if (++nextmode >= vidtbllen)
  1674.         nextlinenum = 32767;
  1675.      else
  1676.         nextlinenum = cfglinenums[nextmode];
  1677.      }
  1678.       else
  1679.      fputs(buf,outfile);
  1680.       }
  1681.  
  1682.    fclose(cfgfile);
  1683.    fclose(outfile);
  1684.    unlink(cfgname);        /* success assumed on these lines        */
  1685.    rename(outname,cfgname); /* since we checked earlier with access */
  1686. #endif
  1687. }
  1688.  
  1689. /* make_mig() takes a collection of individual GIF images (all
  1690.    presumably the same resolution and all presumably generated
  1691.    by Fractint and its "divide and conquer" algorithm) and builds
  1692.    a single multiple-image GIF out of them.  This routine is
  1693.    invoked by the "batch=stitchmode/x/y" option, and is called
  1694.    with the 'x' and 'y' parameters
  1695. */
  1696.  
  1697. void make_mig(unsigned int xmult, unsigned int ymult)
  1698. {
  1699. unsigned int xstep, ystep;
  1700. unsigned int xres, yres;
  1701. unsigned int allxres, allyres, xtot, ytot;
  1702. unsigned int xloc, yloc;
  1703. unsigned char ichar;
  1704. unsigned int allitbl, itbl;
  1705. unsigned int i;
  1706. char gifin[15], gifout[15];
  1707. int errorflag, inputerrorflag;
  1708. unsigned char *temp;
  1709. FILE *out, *in;
  1710. char msgbuf[81];
  1711.  
  1712. errorflag = 0;                /* no errors so far */
  1713. inputerrorflag = 0;
  1714. allxres = allyres = allitbl = 0;
  1715. out = in = NULL;
  1716.  
  1717. strcpy(gifout,"fractmig.gif");
  1718.  
  1719. temp= &olddacbox[0][0];            /* a safe place for our temp data */
  1720.  
  1721. gif87a_flag = 1;            /* for now, force this */
  1722.  
  1723. /* process each input image, one at a time */
  1724. for (ystep = 0; ystep < ymult; ystep++) {
  1725.     for (xstep = 0; xstep < xmult; xstep++) {
  1726.  
  1727. if (xstep == 0 && ystep == 0) {        /* first time through? */
  1728.     static FCODE msg1[] = "Cannot create output file %s!\n";
  1729.     static FCODE msg2[] = " \n Generating multi-image GIF file %s using";
  1730.     static FCODE msg3[] = " %d X and %d Y components\n\n";
  1731.     far_strcpy(msgbuf, msg2);
  1732.     printf(msgbuf, gifout);
  1733.     far_strcpy(msgbuf, msg3);
  1734.     printf(msgbuf, xmult, ymult);
  1735.     /* attempt to create the output file */
  1736.     if ((out = fopen(gifout,"wb")) == NULL) {
  1737.         far_strcpy(msgbuf, msg1);
  1738.         printf(msgbuf, gifout);
  1739.         exit(1);
  1740.         }
  1741.     }
  1742.  
  1743.         sprintf(gifin, "frmig_%c%c.gif", PAR_KEY(xstep), PAR_KEY(ystep));
  1744.  
  1745.         if ((in = fopen(gifin,"rb")) == NULL) {
  1746.             static FCODE msg1[] = "Can't open file %s!\n";
  1747.             far_strcpy(msgbuf, msg1);
  1748.             printf(msgbuf, gifin);
  1749.             exit(1);
  1750.             }
  1751.  
  1752.         /* (read, but only copy this if it's the first time through) */
  1753.         if (fread(temp,13,1,in) != 1)    /* read the header and LDS */
  1754.             inputerrorflag = 1;
  1755.         memcpy(&xres, &temp[6], 2);    /* X-resolution */
  1756.         memcpy(&yres, &temp[8], 2);    /* Y-resolution */
  1757.  
  1758.         if (xstep == 0 && ystep == 0) {    /* first time through? */
  1759.             allxres = xres;        /* save the "master" resolution */
  1760.             allyres = yres;
  1761.             xtot = xres * xmult;    /* adjust the image size */
  1762.             ytot = yres * ymult;
  1763.             memcpy(&temp[6], &xtot, 2);
  1764.             memcpy(&temp[8], &ytot, 2);
  1765.             if (gif87a_flag) {
  1766.                 temp[3] = '8';
  1767.                 temp[4] = '7';
  1768.                 temp[5] = 'a';
  1769.                 }
  1770.             if (fwrite(temp,13,1,out) != 1)    /* write out the header */
  1771.                 errorflag = 1;
  1772.             }                /* end of first-time-through */
  1773.  
  1774.  
  1775.         ichar = (char)(temp[10] & 0x07);    /* find the color table size */
  1776.         itbl = 1 << (++ichar);
  1777.         ichar = (char)(temp[10] & 0x80);    /* is there a global color table? */
  1778.         if (xstep == 0 && ystep == 0)    /* first time through? */
  1779.             allitbl = itbl;        /* save the color table size */
  1780.         if (ichar != 0) {        /* yup */
  1781.             /* (read, but only copy this if it's the first time through) */
  1782.             if(fread(temp,3*itbl,1,in) != 1)    /* read the global color table */
  1783.                 inputerrorflag = 2;
  1784.             if (xstep == 0 && ystep == 0)    /* first time through? */
  1785.                 if (fwrite(temp,3*itbl,1,out) != 1)    /* write out the GCT */
  1786.                     errorflag = 2;
  1787.             }
  1788.  
  1789.         if (xres != allxres || yres != allyres || itbl != allitbl) {
  1790.             /* Oops - our pieces don't match */
  1791.             static FCODE msg1[] = "File %s doesn't have the same resolution as its predecessors!\n";
  1792.             far_strcpy(msgbuf, msg1);
  1793.             printf(msgbuf, gifin);
  1794.             exit(1);
  1795.             }
  1796.  
  1797.         for (;;) {            /* process each information block */
  1798.         if (fread(temp,1,1,in) != 1)    /* read the block identifier */
  1799.             inputerrorflag = 3;
  1800.  
  1801.         if (temp[0] == 0x2c) {        /* image descriptor block */
  1802.             if (fread(&temp[1],9,1,in) != 1)    /* read the Image Descriptor */
  1803.                 inputerrorflag = 4;
  1804.             memcpy(&xloc, &temp[1], 2);    /* X-location */
  1805.             memcpy(&yloc, &temp[3], 2);    /* Y-location */
  1806.             xloc += (xstep * xres);    /* adjust the locations */
  1807.             yloc += (ystep * yres);
  1808.             memcpy(&temp[1], &xloc, 2);
  1809.             memcpy(&temp[3], &yloc, 2);
  1810.             if (fwrite(temp,10,1,out) != 1)    /* write out the Image Descriptor */
  1811.                 errorflag = 4;
  1812.  
  1813.             ichar = (char)(temp[9] & 0x80);    /* is there a local color table? */
  1814.             if (ichar != 0) {        /* yup */
  1815.                 if (fread(temp,3*itbl,1,in) != 1)    /* read the local color table */
  1816.                     inputerrorflag = 5;
  1817.                 if (fwrite(temp,3*itbl,1,out) != 1)    /* write out the LCT */
  1818.                     errorflag = 5;
  1819.                 }
  1820.  
  1821.             if (fread(temp,1,1,in) != 1)    /* LZH table size */
  1822.                 inputerrorflag = 6;
  1823.             if (fwrite(temp,1,1,out) != 1)
  1824.                 errorflag = 6;
  1825.             for(;;) {
  1826.                 if (errorflag != 0 || inputerrorflag != 0)    /* oops - did something go wrong? */
  1827.                     break;
  1828.                 if (fread(temp,1,1,in) != 1)    /* block size */
  1829.                     inputerrorflag = 7;
  1830.                 if (fwrite(temp,1,1,out) != 1)
  1831.                     errorflag = 7;
  1832.                 if ((i = temp[0]) == 0)
  1833.                     break;
  1834.                 if (fread(temp,i,1,in) != 1)    /* LZH data block */
  1835.                     inputerrorflag = 8;
  1836.                 if (fwrite(temp,i,1,out) != 1)
  1837.                     errorflag = 8;
  1838.                 }
  1839.             }
  1840.  
  1841.         if (temp[0] == 0x21) {        /* extension block */
  1842.             /* (read, but only copy this if it's the last time through) */
  1843.             if (fread(&temp[2],1,1,in) != 1)    /* read the block type */
  1844.                 inputerrorflag = 9;
  1845.             if ((!gif87a_flag) && xstep == xmult-1 && ystep == ymult-1)
  1846.                 if (fwrite(temp,2,1,out) != 1)
  1847.                     errorflag = 9;
  1848.             for(;;) {
  1849.                 if (errorflag != 0 || inputerrorflag != 0)    /* oops - did something go wrong? */
  1850.                     break;
  1851.                 if (fread(temp,1,1,in) != 1)    /* block size */
  1852.                     inputerrorflag = 10;
  1853.                 if ((!gif87a_flag) && xstep == xmult-1 && ystep == ymult-1)
  1854.                     if (fwrite(temp,1,1,out) != 1)
  1855.                         errorflag = 10;
  1856.                 if ((i = temp[0]) == 0)
  1857.                     break;
  1858.                 if (fread(temp,i,1,in) != 1)    /* data block */
  1859.                     inputerrorflag = 11;
  1860.                 if ((!gif87a_flag) && xstep == xmult-1 && ystep == ymult-1)
  1861.                     if (fwrite(temp,i,1,out) != 1)
  1862.                         errorflag = 11;
  1863.                 }
  1864.             }
  1865.  
  1866.         if (temp[0] == 0x3b) {        /* end-of-stream indicator */
  1867.             break;            /* done with this file */
  1868.             }
  1869.  
  1870.         if (errorflag != 0 || inputerrorflag != 0)    /* oops - did something go wrong? */
  1871.             break;
  1872.  
  1873.         }
  1874.         fclose(in);            /* done with an input GIF */
  1875.  
  1876.         if (errorflag != 0 || inputerrorflag != 0)    /* oops - did something go wrong? */
  1877.             break;
  1878.         }
  1879.  
  1880.     if (errorflag != 0 || inputerrorflag != 0)    /* oops - did something go wrong? */
  1881.         break;
  1882.     }
  1883.  
  1884. temp[0] = 0x3b;            /* end-of-stream indicator */
  1885. if (fwrite(temp,1,1,out) != 1)
  1886.     errorflag = 12;
  1887. fclose(out);            /* done with the output GIF */
  1888.  
  1889. if (inputerrorflag != 0) {    /* uh-oh - something failed */
  1890.     static FCODE msg1[] = "\007 Process failed = early EOF on input file %s\n";
  1891.     far_strcpy(msgbuf, msg1);
  1892.     printf(msgbuf, gifin);
  1893. /* following line was for debugging
  1894.     printf("inputerrorflag = %d\n", inputerrorflag);
  1895. */
  1896.     }
  1897.  
  1898. if (errorflag != 0) {        /* uh-oh - something failed */
  1899.     static FCODE msg1[] = "\007 Process failed = out of disk space?\n";
  1900.     far_strcpy(msgbuf, msg1);
  1901.     printf(msgbuf);
  1902. /* following line was for debugging
  1903.     printf("errorflag = %d\n", errorflag);
  1904. */
  1905.     }
  1906.  
  1907. /* now delete each input image, one at a time */
  1908. if (errorflag == 0 && inputerrorflag == 0)
  1909.   for (ystep = 0; ystep < ymult; ystep++) {
  1910.     for (xstep = 0; xstep < xmult; xstep++) {
  1911.         sprintf(gifin, "frmig_%c%c.gif", PAR_KEY(xstep), PAR_KEY(ystep));
  1912.         remove(gifin);
  1913.         }
  1914.     }
  1915.  
  1916. /* tell the world we're done */
  1917. if (errorflag == 0 && inputerrorflag == 0) {
  1918.     static FCODE msg1[] = "File %s has been created (and its component files deleted)\n";
  1919.     far_strcpy(msgbuf, msg1);
  1920.     printf(msgbuf, gifout);
  1921.     }
  1922. }
  1923.  
  1924. /* This routine copies the current screen to by flipping x-axis, y-axis,
  1925.    or both. Refuses to work if calculation in progress or if fractal
  1926.    non-resumable. Clears zoombox if any. Resets corners so resulting fractal
  1927.    is still valid. */
  1928. void flip_image(int key)
  1929. {
  1930.    int i, j, ixhalf, iyhalf, tempdot;
  1931.  
  1932.    /* fractal must be rotate-able and be finished */
  1933.    if ((curfractalspecific->flags&NOROTATE) != 0 
  1934.        || calc_status == 1   
  1935.        || calc_status == 2)  
  1936.       return;
  1937.    if(bf_math)
  1938.        clear_zoombox(); /* clear, don't copy, the zoombox */
  1939.    ixhalf = xdots / 2;  
  1940.    iyhalf = ydots / 2;
  1941.    switch(key)
  1942.    {
  1943.    case 24:            /* control-X - reverse X-axis */
  1944.       for (i = 0; i < ixhalf; i++) 
  1945.       {
  1946.          if(keypressed())
  1947.             break;
  1948.          for (j = 0; j < ydots; j++) 
  1949.          {
  1950.             tempdot=getcolor(i,j);
  1951.             putcolor(i, j, getcolor(xdots-1-i,j));
  1952.             putcolor(xdots-1-i, j, tempdot);
  1953.          }
  1954.       }
  1955.       sxmin = xxmax + xxmin - xx3rd;
  1956.       symax = yymax + yymin - yy3rd;
  1957.       sxmax = xx3rd;
  1958.       symin = yy3rd;
  1959.       sx3rd = xxmax;
  1960.       sy3rd = yymin;
  1961.       if(bf_math)
  1962.       {
  1963.          add_bf(bfsxmin, bfxmax, bfxmin); /* sxmin = xxmax + xxmin - xx3rd; */
  1964.          sub_a_bf(bfsxmin, bfx3rd);
  1965.          add_bf(bfsymax, bfymax, bfymin); /* symax = yymax + yymin - yy3rd; */
  1966.          sub_a_bf(bfsymax, bfy3rd);
  1967.          copy_bf(bfsxmax, bfx3rd);        /* sxmax = xx3rd; */
  1968.          copy_bf(bfsymin, bfy3rd);        /* symin = yy3rd; */
  1969.          copy_bf(bfsx3rd, bfxmax);        /* sx3rd = xxmax; */
  1970.          copy_bf(bfsy3rd, bfymin);        /* sy3rd = yymin; */
  1971.       }
  1972.       break;
  1973.    case 25:            /* control-Y - reverse Y-aXis */
  1974.       for (j = 0; j < iyhalf; j++)
  1975.       {
  1976.          if(keypressed())
  1977.             break;
  1978.          for (i = 0; i < xdots; i++) 
  1979.          {
  1980.             tempdot=getcolor(i,j);
  1981.             putcolor(i, j, getcolor(i,ydots-1-j));
  1982.             putcolor(i,ydots-1-j, tempdot);
  1983.          }
  1984.       }
  1985.       sxmin = xx3rd;
  1986.       symax = yy3rd;
  1987.       sxmax = xxmax + xxmin - xx3rd;
  1988.       symin = yymax + yymin - yy3rd;
  1989.       sx3rd = xxmin;
  1990.       sy3rd = yymax;
  1991.       if(bf_math)
  1992.       {
  1993.          copy_bf(bfsxmin, bfx3rd);        /* sxmin = xx3rd; */
  1994.          copy_bf(bfsymax, bfy3rd);        /* symax = yy3rd; */
  1995.          add_bf(bfsxmax, bfxmax, bfxmin); /* sxmax = xxmax + xxmin - xx3rd; */
  1996.          sub_a_bf(bfsxmax, bfx3rd);
  1997.          add_bf(bfsymin, bfymax, bfymin); /* symin = yymax + yymin - yy3rd; */
  1998.          sub_a_bf(bfsymin, bfy3rd);
  1999.          copy_bf(bfsx3rd, bfxmin);        /* sx3rd = xxmin; */
  2000.          copy_bf(bfsy3rd, bfymax);        /* sy3rd = yymax; */
  2001.       }
  2002.       break;
  2003.    case 26:            /* control-Z - reverse X and Y aXis */
  2004.       for (i = 0; i < ixhalf; i++) 
  2005.       {
  2006.          if(keypressed())
  2007.             break;
  2008.          for (j = 0; j < ydots; j++) 
  2009.          {
  2010.             tempdot=getcolor(i,j);
  2011.             putcolor(i, j, getcolor(xdots-1-i,ydots-1-j));
  2012.             putcolor(xdots-1-i, ydots-1-j, tempdot);
  2013.          }
  2014.       }
  2015.       sxmin = xxmax;
  2016.       symax = yymin;
  2017.       sxmax = xxmin;
  2018.       symin = yymax;
  2019.       sx3rd = xxmax + xxmin - xx3rd;
  2020.       sy3rd = yymax + yymin - yy3rd;
  2021.       if(bf_math)
  2022.       {
  2023.          copy_bf(bfsxmin, bfxmax);        /* sxmin = xxmax; */
  2024.          copy_bf(bfsymax, bfymin);        /* symax = yymin; */
  2025.          copy_bf(bfsxmax, bfxmin);        /* sxmax = xxmin; */
  2026.          copy_bf(bfsymin, bfymax);        /* symin = yymax; */
  2027.          add_bf(bfsx3rd, bfxmax, bfxmin); /* sx3rd = xxmax + xxmin - xx3rd; */
  2028.          sub_a_bf(bfsx3rd, bfx3rd);
  2029.          add_bf(bfsy3rd, bfymax, bfymin); /* sy3rd = yymax + yymin - yy3rd; */
  2030.          sub_a_bf(bfsy3rd, bfy3rd);
  2031.       }
  2032.       break;
  2033.    }
  2034.    reset_zoom_corners();
  2035.    calc_status = 0;
  2036. }
  2037.